/* Copyright Thanh-Trung Pham, 2015 */
package jp.ac.uaizu.control;

import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.StringReader;
import java.util.Properties;

/**
 * @author Thanh-Trung Pham
 */
public class RunConfigurationSettings {
    public static final String DEFAULT_SIMULATION_DEPTH_AS_STRING = "100000";
    public static final int DEFAULT_SIMULATION_DEPTH = 100000;

    public static final String DEFAULT_SIMULATION_TIME_AS_STRING = "10";
    public static final int DEFAULT_SIMULATION_TIME = 10;

    private String m_strRunConfigurationSettings;
    private boolean m_bIsAnalyticalCalculationRequired = false;
    private int m_iNumberOfSimulationsRequired = 0;
    private int m_iSimulationDepth = 100000;
    private int m_iSimulationTime = 10;

    /**
     * The constructor.
     *
     * @param runConfigurationSettings the run configuration settings.
     */
    public RunConfigurationSettings(String runConfigurationSettings) {
        m_strRunConfigurationSettings = runConfigurationSettings;
        load();
    }

    /**
     * Check if an analytical calculation is required.
     *
     * @return true if an analytical calculation is required, otherwise false.
     */
    public boolean isAnalyticalCalculationRequired() {
        return m_bIsAnalyticalCalculationRequired;
    }

    /**
     * Get the number of simulations required.
     *
     * @return the number of simulations required.
     */
    public int getNumberOfSimulationsRequired() {
        return m_iNumberOfSimulationsRequired;
    }

    /**
     * Get the simulation depth.
     *
     * @return the simulation depth.
     */
    public int getSimulationDepth() {
        return m_iSimulationDepth;
    }

    /**
     * Get the simulation time.
     *
     * @return the simulation time.
     */
    public int getSimulationTime() {
        return m_iSimulationTime;
    }

    /**
     * Load the run configuration settings.
     */
    private void load() {
        Properties oRunConfigurationSettings = new Properties();
        try {
            oRunConfigurationSettings.load(new StringReader(m_strRunConfigurationSettings));

            loadPredictionMethod(oRunConfigurationSettings);
            loadSimulationDepth(oRunConfigurationSettings);
            loadMaxSimulationTime(oRunConfigurationSettings);

            makeCorrection();
        } catch (IOException oIOEx) {
            oIOEx.printStackTrace();
            loadDefaultRunConfigurationSetting();
        }
    }

    /**
     * Make corrections.
     */
    private void makeCorrection() {
        if(m_bIsAnalyticalCalculationRequired){
            m_iNumberOfSimulationsRequired = 0;
            m_iSimulationTime =0;
            m_iSimulationDepth =0;
        }else{
            if (m_iSimulationTime == 0 && m_iSimulationDepth == 0
                    && m_iNumberOfSimulationsRequired > 0) {
                m_iSimulationDepth = DEFAULT_SIMULATION_DEPTH;
            }
        }

    }

    /**
     * Load the simulation depth.
     *
     * @param oRunConfigurationSettings the run configuration settings.
     */
    private void loadSimulationDepth(Properties oRunConfigurationSettings) {
        try {
            m_iSimulationDepth = Integer.parseInt(oRunConfigurationSettings.getProperty("simulation.depth", DEFAULT_SIMULATION_DEPTH_AS_STRING));
            if ((m_iSimulationDepth < DEFAULT_SIMULATION_DEPTH) && (m_iSimulationDepth != 0)) {
                m_iSimulationDepth = DEFAULT_SIMULATION_DEPTH;
            }
        } catch (NumberFormatException oNFEx) {
            m_iSimulationDepth = DEFAULT_SIMULATION_DEPTH;
        }
    }

    /**
     * Load the max simulation time.
     *
     * @param oRunConfigurationSettings the run configuration settings.
     */
    private void loadMaxSimulationTime(Properties oRunConfigurationSettings) {
        try {
            m_iSimulationTime = Integer.parseInt(oRunConfigurationSettings.getProperty("simulation.time", DEFAULT_SIMULATION_TIME_AS_STRING));
            if ((m_iSimulationTime < DEFAULT_SIMULATION_TIME) && (m_iSimulationTime != 0)) {
                m_iSimulationTime = DEFAULT_SIMULATION_TIME;
            }
        } catch (NumberFormatException oNFEx) {
            m_iSimulationTime = DEFAULT_SIMULATION_TIME;
        }
    }

    /**
     * Load the prediction method.
     *
     * @param runConfigurationSettings the run configuration settings.
     */
    private void loadPredictionMethod(Properties runConfigurationSettings) {
        String strPredictionMethod = runConfigurationSettings.getProperty("prediction.method");
        m_bIsAnalyticalCalculationRequired = StringUtils.contains(strPredictionMethod, "a");

        m_iNumberOfSimulationsRequired = (StringUtils.countMatches(strPredictionMethod, "s"));
        if (m_iNumberOfSimulationsRequired == 0) {
            m_bIsAnalyticalCalculationRequired = true;
        }
    }

    /**
     * Load default run configuration settings.
     */
    private void loadDefaultRunConfigurationSetting() {
        m_bIsAnalyticalCalculationRequired = true;
    }


}
